package com.quanyan.authority.service.impl;

import com.lefu.commons.utils.Page;
import com.quanyan.api.APIResponse;
import com.quanyan.authority.cache.AuthorityRedisTemplate;
import com.quanyan.authority.constants.AuthorityConstants;
import com.quanyan.authority.mapper.RoleMapper;
import com.quanyan.authority.mapper.TbAuthorityMapper;
import com.quanyan.authority.mapper.TbRoleMapper;
import com.quanyan.authority.model.db.*;
import com.quanyan.authority.model.request.ReqPage;
import com.quanyan.authority.model.request.ReqRole;
import com.quanyan.authority.service.RoleMenuService;
import com.quanyan.authority.service.RoleService;
import com.quanyan.comment.reqeust.ReqRoleParams;
import com.quanyan.comment.response.RespAuthority;
import com.quanyan.comment.response.RespSystemRole;
import com.quanyan.common.constants.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.ref.PhantomReference;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by  on 2016/8/1.
 */
@Service
public class RoleServiceImpl implements RoleService {


    private static final Logger logger = LoggerFactory.getLogger(RoleServiceImpl.class);

    @Autowired
    private TbRoleMapper tbRoleMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleMenuService roleMenuService;

    @Autowired
    private AuthorityRedisTemplate authorityRedisTemplate;


    @Override
    public TbRole findById(Integer id) {
        TbRole tbRole = null;
        if(id != null){
            tbRole = (TbRole)authorityRedisTemplate.hget(AuthorityConstants.ROLE_MAP_KEY,id.toString());
            if(tbRole == null)
                tbRole = tbRoleMapper.selectByPrimaryKey(id);
        }
        return tbRole;
    }

    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
    public TbRole add(ReqRole reqBaseParam) {
        TbRole tbRole = new TbRole();
        tbRole.setName(reqBaseParam.getName());
        tbRole.setCode(reqBaseParam.getCode());
        tbRole.setUpdateTime(new Date());
        tbRole.setCreateTime(new Date());
        tbRole.setIsDelete(Constants.IS_DELETE_FALSE);
        tbRole.setRemark(reqBaseParam.getRemark());
        tbRole.setSystemId(reqBaseParam.getSystemId());
        tbRole.setSystemCode(reqBaseParam.getSystemCode());
        tbRoleMapper.insertSelective(tbRole);

        authorityRedisTemplate.hset(AuthorityConstants.ROLE_MAP_KEY,tbRole.getId().toString(),tbRole);
        if (reqBaseParam.getLstMenuId() != null && reqBaseParam.getLstMenuId().size() > 0 ){
            List<TbRoleMenu> lst = new ArrayList<>();
            for (Integer id :reqBaseParam.getLstMenuId()){
                TbRoleMenu tbRoleMenu = new TbRoleMenu();
                tbRoleMenu.setRoleId(tbRole.getId());
                tbRoleMenu.setMenuId(id);
                lst.add(tbRoleMenu);
            }
            roleMenuService.batchAddRoleMenu(lst);
        }
        return tbRole;
    }

    @Override
    public void del(Integer id) {
        tbRoleMapper.deleteByPrimaryKey(id);
        authorityRedisTemplate.hdel(AuthorityConstants.ROLE_MAP_KEY, id.toString());
    }

    @Override
    public void update(ReqRole reqBaseParam) {
        if(reqBaseParam.getId() == null)
            return;
        TbRole tbRole = new TbRole();
        tbRole.setId(reqBaseParam.getId());
        tbRole.setName(reqBaseParam.getName());
        tbRole.setCode(reqBaseParam.getCode());
        tbRole.setRemark(reqBaseParam.getRemark());
        tbRole.setIsDelete(reqBaseParam.getIsDelete().byteValue());
        tbRole.setUpdateTime(new Date());
        tbRole.setFounder(reqBaseParam.getFounder());
        tbRoleMapper.updateByPrimaryKeySelective(tbRole);
        authorityRedisTemplate.hset(AuthorityConstants.ROLE_MAP_KEY,tbRole.getId().toString(),tbRoleMapper.selectByPrimaryKey(tbRole.getId()));

        if (reqBaseParam.getLstRmId() != null && reqBaseParam.getLstRmId().size() > 0 ){
            if(reqBaseParam.getType().intValue() == 1){
                roleMenuService.batchAddRoleMenu(reqBaseParam.getLstRmId());
            }else if(reqBaseParam.getType().intValue() == 2){
                roleMenuService.batchDelRoleMenu(reqBaseParam.getLstRmId());
            }
        }

    }

    @Override
    public Page findAll(ReqPage reqPage, ReqRole reqBaseParam) {
   /*     TbRoleExample example = new TbRoleExample();
        TbRoleExample.Criteria criteria= example.createCriteria();
        criteria.andCodeEqualTo(reqBaseParam.getCode());
        criteria.andNameEqualTo(reqBaseParam.getName());
        criteria.andIsDeleteEqualTo(reqBaseParam.getIsDelete().byteValue());
      //  criteria.andFounderEqualTo(reqBaseParam.getFounder());
       // criteria.andSystemCodeEqualTo(reqBaseParam.getSystemCode());
      //  criteria.andSystemIdEqualTo(reqBaseParam.getSystemId());

        int total = tbRoleMapper.countByExample(example);
        int pageNum = reqPage.getPageNum();
        int pageSize = reqPage.getPageSize();

        example.setOrderByClause(" id desc");
        example.setPage(com.quanyan.common.Plugin.Page.createPage(total, pageNum, pageSize));
        List<TbRole> lst  = tbRoleMapper.selectByExample(example);*/
        Page page = new Page();
        page.setCurrentPage(reqPage.getPageNum());
        page.setCurrentResult(reqBaseParam.getPageSize());
        page.setObject(roleMapper.findAll(page,reqBaseParam.toMap()));

        return page;
    }


   public void initRole(){
       logger.info("缓存角色---");
       TbRoleExample example = new TbRoleExample();
       TbRoleExample.Criteria criteria= example.createCriteria();
       criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
       List<TbRole> lstRole = tbRoleMapper.selectByExample(example);
       for (TbRole r :lstRole){
           authorityRedisTemplate.hset(AuthorityConstants.ROLE_MAP_KEY,r.getId().toString(),r);
           authorityRedisTemplate.set(AuthorityConstants.ROLE_CODE_KEY_REDIS + r.getCode(),r );
       }
       logger.info("结束缓存角色---");
   }

    @Override
    public APIResponse<List<RespSystemRole>> getRoleBySystemCode(String systemCode) {
        if(systemCode == null)
            return APIResponse.returnFail("systemCode不能为空");

        List<RespSystemRole> lstResp= new ArrayList<>();
        TbRoleExample tbRoleExample = new TbRoleExample();
        TbRoleExample.Criteria criteria = tbRoleExample.createCriteria();
        criteria.andSystemCodeEqualTo(systemCode);
        criteria.andIsDeleteEqualTo(Constants.IS_DELETE_FALSE);
        try {
            List<TbRole> lst =  tbRoleMapper.selectByExample(tbRoleExample);
            for (TbRole r: lst){
                RespSystemRole sr = new RespSystemRole();
                sr.setRoleCode(r.getCode());
                sr.setRoleId(r.getId());
                sr.setRoleName(r.getName());
                lstResp.add(sr);
            }
            return APIResponse.returnSuccess(lstResp);
        } catch (Exception e) {
            logger.error("{}",e);
            return APIResponse.returnFail("系统异常！");
        }

    }

    public TbRole getTbRole(String roleCode){
        TbRole tbRole = (TbRole)authorityRedisTemplate.get(AuthorityConstants.ROLE_CODE_KEY_REDIS + roleCode);
        if(tbRole == null){
            TbRoleExample example = new TbRoleExample();
            example.createCriteria().andCodeEqualTo(roleCode);
            List<TbRole>  lst = tbRoleMapper.selectByExample(example);
            if( lst != null && lst.size() > 0){
                tbRole = lst.get(0);
            }
        }
        return tbRole;
    }

    @Override
    public APIResponse<List<RespAuthority>> getAuthorityByRoleCode(String roleCode) {
        if(roleCode == null)
            return APIResponse.returnFail("roleCode不能为空");
        try {
            TbRole tbRole = this.getTbRole(roleCode);//角色
            List<TbRoleMenu> tbRoleMenus =(List<TbRoleMenu>) authorityRedisTemplate.get(AuthorityConstants.ROLE_MENU_REDIS_KEY);//角色拥有的菜单
            Map<Integer,TbMenu> mapMenu =(Map) authorityRedisTemplate.hget(AuthorityConstants.MENU_REDIS_KEY);//系统资源
            List<RespAuthority> respAuthorities = new ArrayList<RespAuthority>();
            for (TbRoleMenu r :tbRoleMenus){
                if (tbRole.getId().intValue() == r.getRoleId().intValue()){
                    TbMenu tbMenu = mapMenu.get(r.getMenuId());
                    if(tbMenu.getType().equals(AuthorityConstants.ResourcesType.function)){
                        RespAuthority respAuthority = new RespAuthority();
                        respAuthority.setAuthorityCode(tbMenu.getCode());
                        respAuthority.setAuthorityId(tbMenu.getId().toString());
                        respAuthority.setAuthorityName(tbMenu.getName());
                        respAuthorities.add(respAuthority);
                    }
                }
            }
            return APIResponse.returnSuccess(respAuthorities);
        } catch (Exception e) {
           logger.error("{}",e);
            return APIResponse.returnFail("系统异常！");
        }
    }


    @Override
    public APIResponse<Boolean> isAuthorityByRole(ReqRoleParams reqRoleParams) {
        try {
            TbRole tbRole = null;
            if(reqRoleParams.getRoleId() != null)
                tbRole = this.findById(reqRoleParams.getRoleId());

            if(reqRoleParams.getRoleCode() != null)
                tbRole = this.getTbRole(reqRoleParams.getRoleCode());

            List<TbRoleMenu> tbRoleMenus =(List<TbRoleMenu>) authorityRedisTemplate.get(AuthorityConstants.ROLE_MENU_REDIS_KEY);//角色拥有的菜单
            Map<Integer,TbMenu> mapMenu =(Map) authorityRedisTemplate.hget(AuthorityConstants.MENU_REDIS_KEY);//系统资源
            for (TbRoleMenu r :tbRoleMenus){
                if (tbRole.getId().intValue() == r.getRoleId().intValue()){
                    TbMenu tbMenu = mapMenu.get(r.getMenuId());
                    if(tbMenu.getType().equals(AuthorityConstants.ResourcesType.function)){
                        if (tbMenu.getUrl().equals(reqRoleParams.getUrl()))
                            return APIResponse.returnSuccess(true);
                        else
                            return APIResponse.returnSuccess(false);

                    }
                }
            }
            return APIResponse.returnSuccess(true);
        } catch (Exception e) {
            logger.error("{}",e);
            return  APIResponse.returnFail("系统异常");
        }

    }
}
